package http.core;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * Created by zhangting on 02/04/2019.
 */
public class Bootstrap {
    private static EventLoopGroup boss = new NioEventLoopGroup(1);
    private static EventLoopGroup work = new NioEventLoopGroup();
    private static Channel channel;


    public static void startHttpServer(int port) {
        try {
            startServer(port);
            shutDownServer();
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static void startServer(int port) throws InterruptedException {
        ServerBootstrap bootstrap = new ServerBootstrap()
                .group(boss, work)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<Channel>() {
                    @Override
                    protected void initChannel(Channel ch) throws Exception {
                        ch.pipeline().addLast("http-decoder", new HttpRequestDecoder());
                        ch.pipeline().addLast("http-aggregator",new HttpObjectAggregator(65536));
                        ch.pipeline()
                                .addLast("http-encoder", new HttpResponseEncoder());
                        ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler());
                        ch.pipeline().addLast("http-handler", new HttpDispatcher());
                        //ch.pipeline().addLast("logging", new LoggingHandler(LogLevel.INFO));

                    }
                }).childOption(ChannelOption.SO_KEEPALIVE, true);
        ;
        ChannelFuture future = bootstrap.bind(port).sync();

        if (future.isSuccess()) {
            System.out.println("server start success,listening on port  "+port);
        }
        channel = future.channel();


    }

    private static void shutDownServer() {
        Runtime.getRuntime().addShutdownHook(new ShutDownHook("shutdown-thread"));
    }

    private static class ShutDownHook extends Thread {
        public ShutDownHook(String name) {
            super(name);
        }

        public void run() {
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }
}
